/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "物理体.h"

#include "../插座/list/list物理物体插座.h"
#include "../插座/list/list矢量插座.h"
#include "../插座/list/list物体插座.h"
#include "../插座/list/list数值插座.h"
#include "../插座/通用插座.h"
#include "../插座/C_数值插座.h"
#include "Context/当前默认操作数据.h"
#include "Context/虚拟体物体构建.h"
#include "Context/数据创建销毁.h"
#include "异步解算/物理异步解算.h"

#include <面/面.h>
#include <物理/物理.h>
#include <Range.h>

//#include <NvFleX封装.h>



S_单色点材质* g_点材质 = nullptr;


static uint32 f_物理体类型转枚举索引(E_物理体类型 type) {
	uint8 物理体类型 = 0;
	switch (type) {
		case E_物理体类型::E_物理体_流体: 物理体类型 = 1; break;
		case E_物理体类型::E_物理体_柔体: 物理体类型 = 2; break;
		case E_物理体类型::E_物理体_布料: 物理体类型 = 3; break;
		case E_物理体类型::E_物理体_流入: 物理体类型 = 4; break;
		case E_物理体类型::E_物理体_刚体: 物理体类型 = 5; break;
		case E_物理体类型::E_物理体_控制: 物理体类型 = 6; break;
		case E_物理体类型::E_物理体_静态: 物理体类型 = 7; break;
		case E_物理体类型::E_物理体_车辆: 物理体类型 = 8; break;
		case E_物理体类型::E_物理体_流出: 物理体类型 = 9; break;
		default:
			break;
	}
	return 物理体类型;
}

static E_物理体类型 f_枚举索引转物理体类型(uint32 index) {
	switch (index) {
		case 1: return E_物理体类型::E_物理体_流体;
		case 2: return E_物理体类型::E_物理体_柔体;
		case 3: return E_物理体类型::E_物理体_布料;
		case 4: return E_物理体类型::E_物理体_流入;
		case 5: return E_物理体类型::E_物理体_刚体;
		case 6: return E_物理体类型::E_物理体_控制;
		case 7: return E_物理体类型::E_物理体_静态;
		case 8: return E_物理体类型::E_物理体_车辆;
		case 9: return E_物理体类型::E_物理体_流出;
		default:
			break;
	}
	return E_物理体类型::E_物理体_空;
}


static E_物理引擎 f_枚举索引转物理引擎类型(uint32 index) {
	switch (index) {
		case 0: return E_物理引擎::E_物理引擎_Mujoco;
		case 1: return E_物理引擎::E_物理引擎_Bullet;
		case 2: return E_物理引擎::E_物理引擎_PBF;
		case 3: return E_物理引擎::E_物理引擎_PhysX;
		case 4: return E_物理引擎::E_物理引擎_FLIP;
	}
	return E_物理引擎::E_物理引擎_None;
}

/*static uint32 f_物理引擎类型枚转举索引(E_物理引擎 e) {
	switch (e)
	{
	case E_物理引擎::E_物理引擎_FleX: return 1;
	case E_物理引擎::E_物理引擎_PhysX: return 2;
	case E_物理引擎::E_物理引擎_FLIP: return 3;
	case E_物理引擎::E_物理引擎_PBF: return 4;
	case E_物理引擎::E_物理引擎_Bullet: return 5;
	case E_物理引擎::E_物理引擎_ODE: return 6;
	case E_物理引擎::E_物理引擎_NewTon: return 7;
	case E_物理引擎::E_物理引擎_Chrono: return 8;
	default:
		break;
	}
	return 0;
}*/










C_物理碰撞节点::C_物理碰撞节点(S_设备环境& ctx) : C_节点基类(DEF_物理碰撞节点) {
	m_Ctx = ctx;
	f_setWName(u"物理碰撞");
	

}

bool C_物理碰撞节点::f_update() {
	return false;
}

C_节点基类* f_node_创建物理碰撞节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_物理碰撞节点(ctx);
}

C_节点基类* f_node_加载物理碰撞节点(S_设备环境& ctx, FILE* f) {
	C_物理碰撞节点* node = new C_物理碰撞节点(ctx);
	return node;
}

void f_node_保存物理碰撞节点(C_节点基类* n, FILE* f) {
	C_物理碰撞节点* node = dynamic_cast<C_物理碰撞节点*>(n);
}




C_物理几何体节点::C_物理几何体节点(S_设备环境& ctx) : C_节点基类(DEF_物理几何体节点, E_节点类型::e_节点Type_物理几何) {
	f_setWName(u"物理几何体");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建物体_1D插座_I(u"物体");
	DEF_创建Vec3_1D插座_I(u"大小");
	DEF_创建Vec3_1D插座_I(u"方向");
	DEF_创建物理几何体_1D插座_O(u"物理体");

	auto* 大小 = DEF_Vec3插座_1D数据(f_get输入插座(2));
	auto* 方向 = DEF_Vec3插座_1D数据(f_get输入插座(3));
	f_core_array_resize((S_Array*)大小, 1);
	大小->ptr_userData[0] = { 1, 1, 1 };

	f_core_array_resize((S_Array*)方向, 1);
	//vec4 q = f_graph_quat两向量({0,0,1}, {0,1,0});
	方向->ptr_userData[0] = { 0,1,0 };


	m_物理引擎类型 = f_创建物理引擎类型属性数据();
	m_物理引擎类型.m_私有 = true;
	f_prop_enum(m_物理引擎类型) = E_物理引擎::E_物理引擎_Mujoco;
	

	m_几何体类型 = f_alloc_EnumProp(nullptr,
		{ 
			{u"立方体", u""},
			{u"圆柱体", u""},
			{u"球体", u""},
			{u"胶囊", u""},
			{u"凸壳", u""},
			{u"平面", u""},
			{u"网格", u""},
		}
	, u"物理几何体类型", 0);

	m_几何体类型.m_私有 = true;
	f_prop_enum(m_几何体类型) = 0;


	m_重量 = f_alloc_F32Prop(nullptr, u"重量");
	m_重量.m_私有 = true;
	f_prop_F32(m_重量) = 1;

	m_密度 = f_alloc_F32Prop(nullptr, u"密度");
	m_密度.m_私有 = true;
	f_prop_F32(m_密度) = 1;

	m_弹性 = f_alloc_F32Prop(nullptr, u"弹性");
	m_弹性.m_私有 = true;
	f_prop_F32(m_弹性) = 1;

	m_阻尼 = f_alloc_F32Prop(nullptr, u"弹性");
	m_阻尼.m_私有 = true;
	f_prop_F32(m_阻尼) = 1;

	m_边缘距离 = f_alloc_F32Prop(nullptr, u"边缘距离");
	m_边缘距离.m_私有 = true;
	f_prop_F32(m_边缘距离) = 0.001;

	m_摩擦 = f_alloc_Vec3Prop(nullptr, u"摩擦");
	m_摩擦.m_私有 = true;
	f_prop_Vec3(m_摩擦) = { 0.5, 0.5, 0.5 };

	m_旋转惯性 = f_alloc_Vec3Prop(nullptr, u"旋转惯性");
	m_旋转惯性.m_私有 = true;
	f_prop_Vec3(m_旋转惯性) = { 0, 0, 0 };


	m_接触参考 = f_alloc_Vec2Prop(nullptr, u"接触参考 ");
	m_接触参考.m_私有 = true;
	f_prop_Vec2(m_接触参考) = { 0.02, 1.0 };

	m_接触实施 = f_alloc_Vec2Prop(nullptr, u"接触实施");
	m_接触实施.m_私有 = true;
	f_prop_Vec2(m_接触实施) = { 0.9, 0.8 };

	m_接触混合 = f_alloc_F32Prop(nullptr, u"接触混合");
	m_接触混合.m_私有 = true;
	f_prop_F32(m_接触混合) = 1;


	m_碰撞位掩码 = f_alloc_UI32FlagBitsProp(nullptr, u"碰撞位掩码");
	m_碰撞位掩码.m_私有 = true;
	f_prop_UI32(m_碰撞位掩码) = 1;

	m_接触的频率 = f_alloc_UI32Prop(nullptr, u"接触的频率", 1);
	m_接触的频率.m_私有 = true;

	m_接触自由度 = f_alloc_UI32Prop(nullptr, u"接触自由度", 3);
	m_接触自由度.m_私有 = true;



	//m_物体 = f_node_创建虚拟体(m_Ctx);
	//m_物体->m_颜色 = S_RGBA8UI{60,255,60,255};
	//f_node_虚拟体_设置立方体虚拟网格(m_物体);
	//f_node_物体添加到主场景(m_物体);
	f_NodeCtx_录物体类节点(this);
}

C_物理几何体节点::~C_物理几何体节点() {
	f_prop_Release(m_几何体类型);
	f_node_物体从主场景中移除(m_物体);

	f_prop_Release(m_重量);

	for (auto& e : m_物体) {
		f_node_删除物体(e);
	}
	for (auto& e : m_链接可视物体) {
		f_node_删除物体(e);
	}
}

void C_物理几何体节点::f_更新虚拟体绘制属性(S_物体* ob, E_物理几何体类型 几何体类型, const vec3& size, S_Mesh* me) {
	//if(!ob->m_DataNum) return;

	switch (几何体类型) {
		case E_物理几何体类型::E_碰撞几何_方体: {
			me = f_node_虚拟体_设置立方体虚拟网格(ob, S_节点数据::g_me_物理体_立方体);
			auto& 网格属性 = f_mesh_get网格元素绘制属性(me);

			网格属性.m_Scale = 1;
			网格属性.m_XMove = 0;
			网格属性.m_YMove = 0;
			网格属性.m_ZMove = 0;
			网格属性.m_TransformMode = DEF_MESH_LINE_TRANFORMTYPEMODEL_NONE;
			break;
		}
		case E_物理几何体类型::E_碰撞几何_圆柱: {
			me = f_node_虚拟体_设置圆柱体虚拟网格(ob, S_节点数据::g_me_物理体_圆柱体);
			auto& 网格属性 = f_mesh_get网格元素绘制属性(me);

			网格属性.m_Scale = size.x;
			网格属性.m_XMove = size.y * 0.5;
			网格属性.m_YMove = size.y * 0.5;
			网格属性.m_ZMove = size.y * 0.5;
			网格属性.m_TransformMode = DEF_MESH_LINE_TRANFORMTYPEMODEL_Cylinder;
			break;
		}
		case E_物理几何体类型::E_碰撞几何_球体: {
			S_Mesh* me = f_node_虚拟体_设置球体虚拟网格(ob, S_节点数据::g_me_物理体_球体);
			auto& 网格属性 = f_mesh_get网格元素绘制属性(me);

			网格属性.m_Scale = 1;
			网格属性.m_XMove = 0;
			网格属性.m_YMove = 0;
			网格属性.m_ZMove = 0;
			网格属性.m_TransformMode = DEF_MESH_LINE_TRANFORMTYPEMODEL_NONE;
			break;
		}
		case E_物理几何体类型::E_碰撞几何_胶囊: {
			me = f_node_虚拟体_设置胶囊虚拟网格(ob, S_节点数据::g_me_物理体_胶囊);
			auto& 网格属性 = f_mesh_get网格元素绘制属性(me);

			网格属性.m_Scale = size.x;
			网格属性.m_XMove = size.y * 0.5;
			网格属性.m_YMove = size.y * 0.5;
			网格属性.m_ZMove = size.y * 0.5;
			网格属性.m_TransformMode = DEF_MESH_LINE_TRANFORMTYPEMODEL_Cylinder;
			break;
		}
		case E_物理几何体类型::E_碰撞几何_凸壳: {

			break;
		}
		case E_物理几何体类型::E_碰撞几何_平面: {
			me = f_node_虚拟体_设置平面虚拟网格(ob, S_节点数据::g_me_物理体_平面);
			auto& 网格属性 = f_mesh_get网格元素绘制属性(me);

			网格属性.m_Scale = 1;
			网格属性.m_XMove = 0;
			网格属性.m_YMove = 0;
			网格属性.m_ZMove = 0;
			网格属性.m_TransformMode = DEF_MESH_LINE_TRANFORMTYPEMODEL_NONE;
			break;
		}
		case E_物理几何体类型::E_碰撞几何_网格: {
			me = f_node_虚拟体_设置立方体虚拟网格(ob, S_节点数据::g_me_物理体_立方体);
			if (me) {
				//me = f_node_虚拟体_设置模型虚拟网格(ob, me);
				auto& 网格属性 = f_mesh_get网格元素绘制属性(me);

				网格属性.m_Scale = 1;
				网格属性.m_XMove = 0;
				网格属性.m_YMove = 0;
				网格属性.m_ZMove = 0;
				网格属性.m_TransformMode = DEF_MESH_LINE_TRANFORMTYPEMODEL_NONE;
			}
			
			break;
		}
		case E_物理几何体类型::E_碰撞几何_地形: {
			auto& 网格属性 = f_mesh_get网格元素绘制属性(me);
			网格属性.m_Scale = 1;
			网格属性.m_XMove = 0;
			网格属性.m_YMove = 0;
			网格属性.m_ZMove = 0;
			网格属性.m_TransformMode = DEF_MESH_LINE_TRANFORMTYPEMODEL_NONE;
			break;
		}
	}

	if (me) {
		me->m_Color = S_RGBA8UI{ 60,255,60,255 };
	}
}

void C_物理几何体节点::f_创建操作虚拟体(S_物体** 几何体, S_物体** 链接轴) {
	if (几何体[0]) {
		auto me0 = f_node_虚拟体_设置立方体虚拟网格(几何体[0]);
		me0->m_Color = S_RGBA8UI{ 40,190,60,255 };
	}
	else {
		几何体[0] = f_node_创建虚拟体(m_Ctx);
		几何体[0]->m_颜色 = S_RGBA8UI{ 60,255,60,255 };
	}
	
	

	if (链接轴[0]) {
		auto me1 = f_node_虚拟体_设置十字叉虚拟网格(链接轴[0]);
		me1->m_Color = S_RGBA8UI{ 40,190,60,255 };
	}
	else {
		链接轴[0] = f_node_创建虚拟体(m_Ctx);
		链接轴[0]->m_颜色 = S_RGBA8UI{ 60,255,60,255 };
		
	}
	
	

	链接轴[0]->m_视口显示模式 = 196611;
	几何体[0]->m_视口显示模式 = 196611;
}

bool C_物理几何体节点::f_update() {
	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);
	auto* socket3 = f_get输入插座(3);

	auto* 输入物体 = DEF_物体插座_1D数据(socket1);
	auto* 大小 = DEF_Vec3插座_1D数据(socket2);
	auto* 方向 = DEF_Vec3插座_1D数据(socket3);
	auto* 物理几何体 = DEF_物理几何插座_1D数据(f_get输出插座(1));

	uint32 num = 输入物体->count;
	//uint32 num = m_物体.size();
	uint32 old_num = 物理几何体->count;

	
	
	vec3 size = 大小->ptr_userData[0];
	E_物理几何体类型 几何体类型 = E_物理几何体类型(f_prop_enum(m_几何体类型));
	bool 参数单例 = 大小->count >= num;


	
	f_node_物体从主场景中移除(m_物体);

	if (num) {
		for (uint32 i = num; i < old_num; ++i) {
			f_node_删除物体((S_物体*)物理几何体->ptr_userData[i]->m_绑定内置物体);
			f_phy_销毁几何体(物理几何体->ptr_userData[i]);
		}

		f_core_array_resize((S_Array*)物理几何体, num);
		m_物体.resize(num);
		m_链接可视物体.resize(num);
		for (uint32 i = old_num; i < num; ++i) {
			if (!m_物体[i]) {
				//S_物体* ob[2] = { m_物体[i], m_链接可视物体[i] };
				
			}
			f_创建操作虚拟体(&m_物体[i], &m_链接可视物体[i]);
			
			物理几何体->ptr_userData[i] = f_phy_创建几何体(几何体类型, {});
		}


		for (uint32 i = 0; i < num; ++i) {
			if (物理几何体->ptr_userData[i]->m_Type != 几何体类型) {
				f_phy_创建几何体数据(物理几何体->ptr_userData[i], 几何体类型);
			}
			
			物理几何体->ptr_userData[i]->m_绑定内置物体 = m_物体[i];
			物理几何体->ptr_userData[i]->m_绑定网格物体 = 输入物体->ptr_userData[i];


			f_ob_clear子物体(m_物体[i]);
			if (输入物体->ptr_userData[i]) {
				输入物体->ptr_userData[i]->m_父级变换关系 = E_父级变换关系::e_变换关系_继承;

				f_ob_add子物体(m_物体[i], 输入物体->ptr_userData[i]);
				f_ob_add子物体(m_物体[i], m_链接可视物体[i]);
			}
			f_ob_set附属类型(m_物体[i], E_物体类型::t_物体包);


			switch (几何体类型) {
				case E_物理几何体类型::E_碰撞几何_网格: {
					break;
				}
				default: {
					m_物体[i]->m_变换.scale = 输入物体->ptr_userData[i]->m_变换.scale;
				}
			}

			f_NodeCtx_录物体类节点(this, m_物体[i]);
			f_NodeCtx_录物体类节点(this, m_链接可视物体[i]);
		}
	}
	else {
		f_core_array_resize((S_Array*)物理几何体, 1);
		
		m_物体.resize(1);
		m_链接可视物体.resize(1);
		//if (!m_物体[0]) {
		//}
		f_创建操作虚拟体(&m_物体[0], &m_链接可视物体[0]);
		if (!物理几何体->ptr_userData[0]) {
			物理几何体->ptr_userData[0] = f_phy_创建几何体(几何体类型, {});
		}
		f_ob_clear子物体(m_物体[0]);
		f_ob_add子物体(m_物体[0], m_链接可视物体[0]);


		f_NodeCtx_物体显示模式(m_物体[0], 3);
		f_NodeCtx_物体全局显示模式(m_物体[0], 3);
		f_NodeCtx_物体显示模式(m_链接可视物体[0], 3);
		f_NodeCtx_物体全局显示模式(m_链接可视物体[0], 3);

		f_NodeCtx_录物体类节点(this, m_物体[0]);
		f_NodeCtx_录物体类节点(this, m_链接可视物体[0]);


		switch (几何体类型) {
			case E_物理几何体类型::E_碰撞几何_网格:
			case E_物理几何体类型::E_碰撞几何_地形:
				break;
			default: {
				物理几何体->ptr_userData[0]->m_绑定内置物体 = m_物体[0];
			}
		}
		物理几何体->ptr_userData[0]->m_绑定网格物体 = nullptr;
		num = 1;
	}
	//f_ob_set缩放(m_物体, 大小->ptr_userData[0]);
	

	

	for (uint32 i = 0; i < num; ++i) {
		auto* geom = 物理几何体->ptr_userData[i];
		S_Mesh* me = nullptr;

		switch (几何体类型) {
			case E_物理几何体类型::E_碰撞几何_方体: {
				((S_物理几何_方体*)geom->m_Data)->大小 = 参数单例 ? 大小->ptr_userData[i] : 大小->ptr_userData[0];
				break;
			}

			case E_物理几何体类型::E_碰撞几何_圆柱: {
				((S_物理几何_圆柱*)geom->m_Data)->大小 = 参数单例 ? 大小->ptr_userData[i] : 大小->ptr_userData[0];
				break;
			}

			case E_物理几何体类型::E_碰撞几何_球体: {
				((S_物理几何_球体*)geom->m_Data)->大小 = 参数单例 ? 大小->ptr_userData[i].x : 大小->ptr_userData[0].x;
				break;
			}

			case E_物理几何体类型::E_碰撞几何_胶囊: {
				((S_物理几何_胶囊*)geom->m_Data)->大小 = 参数单例 ? _Vec2(大小->ptr_userData[i]) : _Vec2(大小->ptr_userData[0]);
				break;
			}

			case E_物理几何体类型::E_碰撞几何_凸壳: {
				break;
			}

			case E_物理几何体类型::E_碰撞几何_平面: {
				auto mat = f_mat44_构建XYZ旋转矩阵(((S_物体*)geom->m_绑定内置物体)->m_变换);

				((S_物理几何_平面*)geom->m_Data)->方向 = 参数单例 ? mat * 方向->ptr_userData[i] : mat * 方向->ptr_userData[0];
				//((S_物理几何_平面*)geom->m_Data)->平面 = 大小->ptr_userData[i].w;
				((S_物理几何_平面*)geom->m_Data)->位置 = ((S_物体*)geom->m_绑定内置物体)->m_变换.position;
				break;
			}

			case E_物理几何体类型::E_碰撞几何_网格: {
				if (输入物体->count) {
					me = f_ob_getMesh(输入物体->ptr_userData[i]);

					std::vector<vec3> 顶点;
					f_surface_get顶点坐标(me, 顶点);
					((S_物理几何_网格*)geom->m_Data)->顶点 = f_buf_VNT_ptr(*me->m_顶点);
					((S_物理几何_网格*)geom->m_Data)->索引 = f_buf_UI32_ptr(*me->m_索引);
					((S_物理几何_网格*)geom->m_Data)->顶点数量 = me->m_顶点->m_Mem.m_数量;
					((S_物理几何_网格*)geom->m_Data)->索引数量 = me->m_索引->m_Mem.m_数量;

					((S_物理几何_网格*)geom->m_Data)->方向 = 参数单例 ? 方向->ptr_userData[i] : 方向->ptr_userData[0];
				}
				break;
			}

			case E_物理几何体类型::E_碰撞几何_地形: {
				break;
			}
		}
		geom->m_Type = 几何体类型;

		geom->g_材质.m_重量 = f_prop_F32(m_重量);
		geom->g_材质.m_密度 = f_prop_F32(m_密度);
		geom->g_材质.m_弹性 = f_prop_F32(m_弹性);
		geom->g_材质.m_阻尼 = f_prop_F32(m_阻尼);
		geom->g_材质.m_边缘距离 = f_prop_F32(m_边缘距离);
		geom->g_材质.m_摩擦 = f_prop_Vec3(m_摩擦);
		geom->g_材质.m_旋转惯性 = f_prop_Vec3(m_旋转惯性);

		geom->g_材质.m_接触参考 = f_prop_Vec2(m_接触参考);
		geom->g_材质.m_接触实施 = f_prop_Vec2(m_接触实施);
		geom->g_材质.m_接触混合 = f_prop_F32(m_接触混合);

		geom->g_材质.m_碰撞位掩码 = f_prop_UI32(m_碰撞位掩码);
		geom->g_材质.m_接触的频率 = f_prop_UI32(m_接触的频率);
		geom->g_材质.m_接触自由度 = f_prop_UI32(m_接触自由度);


		f_更新虚拟体绘制属性(m_物体[i], 几何体类型, 参数单例 ? 大小->ptr_userData[i] : 大小->ptr_userData[i], me);
	}


	//for (auto& e : m_物体) {
	//	f_更新虚拟体绘制属性(e, 几何体类型, 参数单例 ? 大小->ptr_userData[i] : 大小->ptr_userData[0]);
	//}
	f_node_物体添加到主场景(m_物体);

	return false;
}

S_物体* C_物理几何体节点::f_虚拟体() {
	//return nullptr;
	return m_物体.size() ? m_物体[0] : nullptr;
	//return m_物体;
}

void C_物理几何体节点::f_删除() {
	f_node_物体从主场景中移除(m_物体);
}

void C_物理几何体节点::f_回收() {
	
}

void C_物理几何体节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_8, S_引擎配置::g_文件版本号)) {
			
			uint32 num = m_物体.size();
			下一次读取数据指针 = f_文件块_读数据块(下一次读取数据指针, num);
			m_物体.resize(num);
			m_链接可视物体.resize(num);
			for (uint32 i=0; i<num; ++i) {
				//S_物体* ob[2] = { m_物体[i], m_链接可视物体[i] };
				f_创建操作虚拟体(&m_物体[i], &m_链接可视物体[i]);

				//下一次读取数据指针 = f_ob_Load物体(m_物体[i], 下一次读取数据指针);
				//下一次读取数据指针 = f_ob_Load物体(m_链接可视物体[i], 下一次读取数据指针);
			}
			//下一次读取数据指针 = f_ob_Load物体(m_物体, 下一次读取数据指针);


			下一次读取数据指针 = f_prop_Load(m_几何体类型, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_重量, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_密度, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_弹性, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_阻尼, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_边缘距离, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_摩擦, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_旋转惯性, 下一次读取数据指针);

			下一次读取数据指针 = f_prop_Load(m_接触参考, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_接触实施, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_接触混合, 下一次读取数据指针);

			下一次读取数据指针 = f_prop_Load(m_碰撞位掩码, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_接触的频率, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_接触自由度, 下一次读取数据指针);

		}
	}
	free(文件块.m_data);

	auto* socket2 = f_get输入插座(2);
	auto* 大小 = DEF_Vec3插座_1D数据(socket2);
	vec3 size = 大小->ptr_userData[0];
	E_物理几何体类型 几何体类型 = E_物理几何体类型(f_prop_enum(m_几何体类型));
	for (auto& e : m_物体) {
		f_更新虚拟体绘制属性(e, 几何体类型, size);
	}

}

void C_物理几何体节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	uint32 num = m_物体.size();
	f_文件块_写数据块(块, num);
	for (uint32 i = 0; i < num; ++i) {
		f_ob_Save物体(m_物体[i], 块);
		f_ob_Save物体(m_链接可视物体[i], 块);
	}
	f_node_物体添加到主场景(m_物体);
	f_node_物体添加到主场景(m_链接可视物体);


	f_prop_Save(m_几何体类型, 块);
	f_prop_Save(m_重量, 块);
	f_prop_Save(m_密度, 块);
	f_prop_Save(m_弹性, 块);
	f_prop_Save(m_阻尼, 块);
	f_prop_Save(m_边缘距离, 块);
	f_prop_Save(m_摩擦, 块);
	f_prop_Save(m_旋转惯性, 块);

	f_prop_Save(m_接触参考, 块);
	f_prop_Save(m_接触实施, 块);
	f_prop_Save(m_接触混合, 块);

	f_prop_Save(m_碰撞位掩码, 块);
	f_prop_Save(m_接触的频率, 块);
	f_prop_Save(m_接触自由度, 块);

	f_file_保存文件块(f, 文件块, 块);
}

void C_物理几何体节点::f_Copy(const C_节点基类* node) {
	const C_物理几何体节点* 被复制节点 = dynamic_cast<const C_物理几何体节点*>(node);

	f_prop_enum(m_几何体类型) = f_prop_enum(被复制节点->m_几何体类型);
	f_prop_F32(m_重量) = f_prop_F32(被复制节点->m_重量);
	f_prop_F32(m_密度) = f_prop_F32(被复制节点->m_密度);
	f_prop_F32(m_弹性) = f_prop_F32(被复制节点->m_弹性);
	f_prop_F32(m_阻尼) = f_prop_F32(被复制节点->m_阻尼);
	f_prop_F32(m_边缘距离) = f_prop_F32(被复制节点->m_边缘距离);
	f_prop_Vec3(m_摩擦) = f_prop_Vec3(被复制节点->m_摩擦);
	f_prop_Vec3(m_旋转惯性) = f_prop_Vec3(被复制节点->m_旋转惯性);

	f_prop_Vec2(m_接触参考) = f_prop_Vec2(被复制节点->m_接触参考);
	f_prop_Vec2(m_接触实施) = f_prop_Vec2(被复制节点->m_接触实施);
	f_prop_F32(m_接触混合) = f_prop_F32(被复制节点->m_接触混合);

	f_prop_UI32(m_碰撞位掩码) = f_prop_UI32(被复制节点->m_碰撞位掩码);
	f_prop_UI32(m_接触的频率) = f_prop_UI32(被复制节点->m_接触的频率);
	f_prop_UI32(m_接触自由度) = f_prop_UI32(被复制节点->m_接触自由度);

}

C_节点基类* f_node_创建物理几何体节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_物理几何体节点(ctx);
}

C_节点基类* f_node_加载物理几何体节点(S_设备环境& ctx, FILE* f) {
	C_物理几何体节点* node = new C_物理几何体节点(ctx);
	return node;
}

void f_node_保存物理几何体节点(C_节点基类* n, FILE* f) {
	C_物理几何体节点* node = dynamic_cast<C_物理几何体节点*>(n);
}





C_物理体节点::C_物理体节点(S_设备环境& ctx) : C_节点基类(DEF_物理体节点, E_节点类型::e_节点Type_物理体) {
	f_setWName(u"物理体节点");
	m_Ctx = ctx;
	m_插座改变后是否更新节点 = true;
	m_是否完成计算 = 0;

	//DEF_创建物体_1D插座_I(u"几何体");
	DEF_创建物理几何体_1D插座_I(u"几何体");
	DEF_创建物理体_1D插座_I(u"子物体");

	DEF_创建物理体_1D插座_O(u"物理体");
	

	
	f_get输入插座(1)->f_set多输入();
	f_get输入插座(2)->f_set多输入();



	m_物理体类型 = f_创建物理体类型属性数据();
	m_物理体类型.m_私有 = true;
	f_prop_enum(m_物理体类型) = 1;
	

	m_物理引擎类型 = f_创建物理引擎类型属性数据();
	f_prop_enum(m_物理引擎类型) = E_物理引擎::E_物理引擎_Mujoco;
	m_物理引擎类型.m_私有 = true;

	m_粒子最大数 = f_alloc_UI32Prop(nullptr, u"发射粒子最大数", 1000);
	m_粒子最大数.m_私有 = true;

	m_填充方式 = f_alloc_EnumProp(nullptr,
		{ {u"实体", u""}
		, {u"表面", u""}
		}
	, u"填充方式", 0);
	m_填充方式.m_私有 = true;

	m_是否多线程 = f_alloc_BoolProp(nullptr, u"多线程");
	m_是否多线程.m_私有 = true;
	f_prop_Bool(m_是否多线程) = false;


	

	m_链接类型 = f_alloc_EnumProp(nullptr, {
		{ u"自由连接", u""},
		{ u"铰链连接", u"铰链" },
		{ u"滑动连接", u"滑动" },
		{ u"球型连接", u"球连接"},
		{ u"固定连接", u""},
		
							  }
	, u"物理体类型", 0);
	m_链接类型.m_私有 = true;

	m_链接轴向 = f_alloc_Vec3Prop(nullptr, u"链接轴向");
	m_链接轴向.m_私有 = true;
	f_prop_Vec3(m_链接轴向) = {1,0,0};

	m_限定范围 = f_alloc_BoolProp(nullptr, u"限定范围");
	m_限定范围.m_私有 = true;
	f_prop_Bool(m_限定范围) = false;

	m_关节范围 = f_alloc_Vec2Prop(nullptr, u"限定范围");
	m_关节范围.m_私有 = true;
	f_prop_Vec2(m_关节范围) = {-1,1};

	m_关节阻尼 = f_alloc_F32Prop(nullptr, u"关节阻尼");
	m_关节阻尼.m_私有 = true;
	f_prop_F32(m_关节阻尼) = 0.2;

	m_关节刚度 = f_alloc_F32Prop(nullptr, u"关节刚度");
	m_关节刚度.m_私有 = true;
	f_prop_F32(m_关节刚度) = 0.2;

	m_关节摩擦 = f_alloc_F32Prop(nullptr, u"关节摩擦");
	m_关节摩擦.m_私有 = true;
	f_prop_F32(m_关节摩擦) = 0.1;


	m_数据可视物体 = f_ob_创建(ctx, E_物体类型::t_网格物体);
	f_ob_set数据槽数量(m_数据可视物体, 1);

	auto* mesh = f_surface_创建网格对象(0, ctx, false, E_网格数据枚举::e_Mesh_Vulkan);
	m_数据可视物体->f_setData(mesh, 0);

	//f_NodeCtx_get当前独立显示物体();
	if (!g_点材质) {
		g_点材质 = new S_单色点材质(ctx);
	}
	f_ob_set材质(m_数据可视物体, g_点材质, 0);

}

C_物理体节点::~C_物理体节点() {
	
	f_prop_Release(m_物理体类型);
	f_prop_Release(m_粒子最大数);
	f_prop_Release(m_填充方式);
	f_prop_Release(m_是否多线程);
	
	f_prop_Release(m_链接类型);
	f_prop_Release(m_限定范围);
	f_prop_Release(m_关节范围);
	f_prop_Release(m_关节阻尼);
	f_prop_Release(m_关节刚度);
	f_prop_Release(m_关节摩擦);
}

bool C_物理体节点::f_update() {
	
	E_物理体类型 物理体类型 = E_物理体类型(f_prop_enum(m_物理体类型));
	E_物理引擎 物理引擎类型 = E_物理引擎(f_prop_enum(m_物理引擎类型));

	auto* out物理体 = DEF_物理体插座_1D数据(f_get输出插座(1));
	uint32 old_num = out物理体->count;

	for (uint32 i = 0; i < old_num; ++i) {
		f_phy_销毁物理体(out物理体->ptr_userData[i]);
	}
	f_core_array_reserve((S_Array*)out物理体, 0);


	auto* socket1 = f_get输入插座(1);
	uint32 LinkNum = socket1->f_getLinkNum();
	uint32 offset = 0;

	for (uint32 线ID = 0; 线ID < LinkNum; ++线ID) {
		S_PhyGeomArray* 物理几何体 = (S_PhyGeomArray*)socket1->f_getData(线ID);

		for (uint32 i=0; i< 物理几何体->count; ++i) {
			auto* 物理几何 = 物理几何体->ptr_userData[i];

			S_物理体* body = nullptr;
			if (offset >= out物理体->count) {
				body = f_phy_create物理体(物理几何, nullptr, 物理引擎类型);
				f_core_array_push_back((S_Array*)out物理体, (uint8*)&body);
			}
			else {
				body = out物理体->ptr_userData[offset];
			}
			
			if (物理几何->m_绑定网格物体) {
				body->m_绑定物体 = 物理几何->m_绑定网格物体;
			}
			else {
				body->m_绑定物体 = 物理几何->m_绑定内置物体;
			}
			if (物理几何->m_绑定内置物体) {
				body->m_虚拟链接轴绑定物体 = ((S_物体*)(物理几何->m_绑定内置物体))->m_子物体.back();
			}
			
			body->m_几何体 = 物理几何;
			body->m_物理体类型 = 物理体类型;
			body->m_链接子物体.clear();
			
			//body->m_质量 = f_prop_F32(m_重量);
			body->m_链接类型 = E_物理体链接类型(f_prop_enum(m_链接类型));
			body->m_限定范围 = f_prop_Bool(m_限定范围);
			body->m_关节范围 = f_prop_Vec2(m_关节范围);
			body->m_关节阻尼 = f_prop_F32(m_关节阻尼);
			body->m_关节刚度 = f_prop_F32(m_关节刚度);
			body->m_关节摩擦 = f_prop_F32(m_关节摩擦);

			
			if (body->m_绑定物体) {
				//body->m_变换 = ((S_物体*)物理几何->m_绑定内置物体)->m_变换;
			}
			

			switch (物理体类型) {
				case E_物理体类型::E_物理体_静态: {
					//body->m_质量 = 0;
					break;
				}
			}
			
			++offset;
		}
	}

	auto* socket2 = f_get输入插座(2);
	LinkNum = socket2->f_getLinkNum();

	std::vector<S_物理体*> 子物理体;
	for (uint32 线ID = 0; 线ID < LinkNum; ++线ID) {
		S_PhyBodyArray* 物理体 = (S_PhyBodyArray*)socket2->f_getData(线ID);

		for (uint32 i = 0; i < 物理体->count; ++i) {
			auto* body = 物理体->ptr_userData[i];

			子物理体.push_back(body);
		}
	}


	if (out物理体->count == 子物理体.size()) {
		for (uint32 i = 0; i < out物理体->count; ++i) {
			out物理体->ptr_userData[i]->m_链接子物体.push_back(子物理体[i]);
		}
	}
	else {
		for (uint32 i = 0; i < out物理体->count; ++i) {
			out物理体->ptr_userData[i]->m_链接子物体 = 子物理体;
		}
	}

	return false;
}

void C_物理体节点::f_异步解算() {
	E_物理体类型 物理体类型 = f_枚举索引转物理体类型(f_prop_enum(m_物理体类型));
	E_物理引擎 物理引擎类型 = f_枚举索引转物理引擎类型(f_prop_enum(m_物理引擎类型));

	auto* out物理体 = DEF_物理体插座_1D数据(f_get输出插座(1), 0);
	float32 解析度 = DEF_F32插座数据(f_get输入插座(1));


	m_是否完成计算 = 2;
}

void C_物理体节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	auto 文件块 = f_file_读取文件块(f);

	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;
		下一次读取数据指针 = f_prop_Load(m_物理引擎类型, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_物理体类型, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_粒子最大数, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_填充方式, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_是否多线程, 下一次读取数据指针);
		

		下一次读取数据指针 = f_prop_Load(m_链接类型, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_限定范围, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_关节范围, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_关节阻尼, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_关节刚度, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_关节摩擦, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_物理体节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);

	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));
	f_prop_Save(m_物理引擎类型, 块);
	f_prop_Save(m_物理体类型, 块);
	f_prop_Save(m_粒子最大数, 块);
	f_prop_Save(m_填充方式, 块);
	f_prop_Save(m_是否多线程, 块);
	
	f_prop_Save(m_链接类型, 块);
	f_prop_Save(m_限定范围, 块);
	f_prop_Save(m_关节范围, 块);
	f_prop_Save(m_关节阻尼, 块);
	f_prop_Save(m_关节刚度, 块);
	f_prop_Save(m_关节摩擦, 块);

	f_file_保存文件块(f, 文件块, 块);
}

S_物体* C_物理体节点::f_虚拟体() {
	
	return nullptr;
}

void C_物理体节点::f_删除() {
	
}

void C_物理体节点::f_回收() {
	
}

void C_物理体节点::f_Copy(const C_节点基类* node) {
	const C_物理体节点* 被复制物体 =  dynamic_cast<const C_物理体节点*>(node);

	f_prop_enum(m_链接类型) = f_prop_enum(被复制物体->m_链接类型);
	f_prop_Vec3(m_链接轴向) = f_prop_Vec3(被复制物体->m_链接轴向);
	f_prop_Bool(m_限定范围) = f_prop_Bool(被复制物体->m_限定范围);
	f_prop_Vec2(m_关节范围) = f_prop_Vec2(被复制物体->m_关节范围);
	f_prop_F32(m_关节阻尼) = f_prop_F32(被复制物体->m_关节阻尼);
	f_prop_F32(m_关节刚度) = f_prop_F32(被复制物体->m_关节刚度);
	f_prop_F32(m_关节摩擦) = f_prop_F32(被复制物体->m_关节摩擦);

}

C_节点基类* f_node_创建物理体节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_物理体节点(ctx);
}

C_节点基类* f_node_加载物理体节点(S_设备环境& ctx, FILE* f) {
	C_物理体节点* node = new C_物理体节点(ctx);
	return node;
}

void f_node_保存物理体节点(C_节点基类* n, FILE* f) {
	C_物理体节点* node = dynamic_cast<C_物理体节点*>(n);
}








C_物理体添加节点::C_物理体添加节点(S_设备环境& ctx) : C_节点基类("物理体添加节点") {
	f_setWName(u"物理体节点");

	C_插座基类* socket;
	DEF_创建物理引擎插座_I(u"物理引擎");
	DEF_创建物理体_1D插座_I(u"物理体");
	
	DEF_创建物理引擎插座_O(u"物理引擎");
	//DEF_创建物理体Array1D插座_O("物理体");
}

bool C_物理体添加节点::f_update() {
	auto* 解算器 = DEF_物理引擎插座数据(f_get输入插座(1), 0);
	
	f_get输出插座(1)->f_setData(解算器);

	if (解算器) {
		uint16 num = f_get输入插座数量();
		for (uint32 i = 2; i < num; ++i) {
			auto* 物理体 = DEF_物理体插座_1D数据(f_get输入插座(i));
			//f_Phy_添加物理体(解算器, 物理体->ptr_userData[i]);
		}
	}
	return false;
}

C_插座基类* C_物理体添加节点::f_动态添加插座(E_插座方向 方向) {
	C_插座基类* socket = nullptr;
	return socket;

	E_数据赋值方式 插座操作方式;

	uint16 num = f_get输入插座数量();
	if (num >= 3 && f_get输入插座(num - 2)->f_isLink() == false) {
		//return { nullptr, E_数据赋值方式::e_赋值_None };
	}

	switch (方向)
	{
	case e_插座Type_输入: {
		DEF_创建物理体_1D插座_I(u"源1");

		插座操作方式 = E_数据赋值方式::e_赋值_添加;
		break;
	}
	case e_插座Type_输出: {

		插座操作方式 = E_数据赋值方式::e_赋值_添加;
		break;
	}
	//default:
	//	return { nullptr, E_数据赋值方式::e_赋值_None };
	}

	f_set是否要更新(true);
	return socket;
}

C_节点基类* f_node_加载物理体添加节点(S_设备环境& ctx, FILE* f) {
	C_物理体添加节点* node = new C_物理体添加节点(ctx);
	return node;
}

void f_node_保存物理体添加节点(C_节点基类* n, FILE* f) {
	C_物理体添加节点* node = dynamic_cast<C_物理体添加节点*>(n);

}




C_取物理体节点::C_取物理体节点(S_设备环境& ctx) : C_节点基类(DEF_取物理体节点) {
	f_setWName(u"取物理体");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建物理引擎插座_I(u"物理引擎");
	DEF_创建物理体_1D插座_O(u"物理体");

	m_物理几何类型 = f_创建物理体类型属性数据();
	m_物理几何类型.m_私有 = true;
	f_prop_enum(m_物理几何类型) = E_物理几何体类型::E_碰撞几何_方体;
}

C_取物理体节点::~C_取物理体节点() {
}

bool C_取物理体节点::f_update() {
	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输入插座(1), 0);
	auto& bodys = *DEF_物理体插座_1D数据(f_get输出插座(1), 0);

	//if (m_Physics) {
	//	bodys = f_phy_get物理体(m_Physics, E_物理几何体类型(f_prop_enum(m_物理几何类型)));
	//}
	//else {
	//	bodys.clear();
	//}
	
	return false;
}

void C_取物理体节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	f_prop_Load(m_物理几何类型, f);
}

void C_取物理体节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	f_prop_Save(m_物理几何类型, f);
}

C_节点基类* f_node_加载取物理体节点(S_设备环境& ctx, FILE* f) {
	C_取物理体节点* node = new C_取物理体节点(ctx);
	return node;
}

void f_node_保存取物理体节点(C_节点基类* n, FILE* f) {
	C_取物理体节点* node = dynamic_cast<C_取物理体节点*>(n);
}





C_物理体绑定物体节点::C_物理体绑定物体节点(S_设备环境& ctx) : C_节点基类(DEF_物理体绑定物体节点) {
	f_setWName(u"绑定物体");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建物理引擎插座_I(u"物理引擎");
	DEF_创建物理体_1D插座_I(u"物理体");
	DEF_创建物体_Array1D插座_I(u"绑定物体");
	
	DEF_创建物理引擎插座_O(u"物理引擎");
	f_get输入插座(1)->f_set单输入();
	
}

C_物理体绑定物体节点::~C_物理体绑定物体节点() {
}

bool C_物理体绑定物体节点::f_update() {
	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输入插座(1), 0);
	auto& bodys = *DEF_物理体插座_1D数据(f_get输入插座(2), 0);
	auto& obs = *DEF_物体插座_Array1D数据(f_get输入插座(3), 0);

	//auto body_ptr = bodys.data();
	//auto ob_ptr = obs.data();
	//
	//uint32 num = bodys.size();
	//if (num <= obs.size()) {
	//	for (uint32 i = 0; i < num; ++i) {
	//		body_ptr[i]->m_绑定物体= ob_ptr[i];
	//		ob_ptr[i]->m_ID = body_ptr[i]->m_ID;
	//	}
	//	if (m_Physics) f_Phy_内部网格填充绑定物体(m_Physics, bodys);
	//}
	f_get输出插座(1)->f_setData(m_Physics);

	return false;
}

void C_物理体绑定物体节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
}

void C_物理体绑定物体节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
}

C_节点基类* f_node_加载物理体绑定物体节点(S_设备环境& ctx, FILE* f) {
	C_物理体绑定物体节点* node = new C_物理体绑定物体节点(ctx);
	return node;
}

void f_node_保存物理体绑定物体节点(C_节点基类* n, FILE* f) {
	C_物理体绑定物体节点* node = dynamic_cast<C_物理体绑定物体节点*>(n);
}





C_物理引擎内部几何节点::C_物理引擎内部几何节点(S_设备环境& ctx) : C_节点基类(DEF_物理引擎内部几何节点) {
	f_setWName(u"内部几何");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建物理引擎插座_I(u"物理引擎");
	DEF_创建物理引擎插座_O(u"物理引擎");

}

C_物理引擎内部几何节点::~C_物理引擎内部几何节点() {
}

bool C_物理引擎内部几何节点::f_update() {
	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输入插座(1));
	if (m_Physics) {
		//f_Phy_内部网格填充绑定物体(m_Physics);
	}
	
	f_get输出插座(1)->f_setData(m_Physics);
	return false;
}

void C_物理引擎内部几何节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
}

void C_物理引擎内部几何节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
}

C_节点基类* f_node_加载物理引擎内部几何节点(S_设备环境& ctx, FILE* f) {
	C_物理引擎内部几何节点* node = new C_物理引擎内部几何节点(ctx);
	return node;
}

void f_node_保存物理引擎内部几何节点(C_节点基类* n, FILE* f) {
	C_物理引擎内部几何节点* node = dynamic_cast<C_物理引擎内部几何节点*>(n);
}




enum E_粒子渲染类型 {
	e_空,
	e_球体,
	e_方体,
	e_模型,
};

C_粒子系统节点::C_粒子系统节点(S_设备环境& ctx) : C_节点基类(DEF_粒子系统节点, E_节点类型::e_节点Type_物理体) {
	m_Ctx = ctx;
	f_setWName(u"粒子系统");
	C_插座基类* socket;

	DEF_创建物理几何体_1D插座_I(u"几何体");
	DEF_创建物体_1D插座_I(u"子物体");
	//DEF_创建F32插座_v1_I(u"粒子数量");
	DEF_创建物理体_1D插座_O(u"物理体");

	m_渲染类型 = f_alloc_EnumProp(nullptr, {
		{u"空"},
		{u"球体"},
		{u"方体"},
		{u"模型"},
	}, u"");
	m_渲染类型.m_私有 = true;

	m_物理体 = f_phy_create物理体(nullptr, nullptr, E_物理引擎::E_物理引擎_PBF);


	m_包含属性 = f_alloc_FlagBitsEnumProp(nullptr, *S_节点数据::g_粒子包含属性, u"包含属性", E_粒子更新属性::e_pu_位置);
	m_包含属性.m_私有 = true;

	m_粒子数量 = f_alloc_UI32Prop(nullptr, u"粒子数量", 1000);
	m_粒子数量.m_私有 = true;

	m_粒子寿命 = f_alloc_F32Prop(nullptr, u"寿命", 4);
	m_粒子寿命.m_私有 = true;

	m_系统名称 = f_alloc_LineStrProp(&m_物理体->m_Name, u"名称");
	m_系统名称.m_私有 = true;

	m_寿命随机比 = f_alloc_F32Prop(nullptr, u"寿命随机比");
	m_寿命随机比.m_私有 = true;

	m_粒子大小 = f_alloc_F32Prop(nullptr, u"粒子大小", 1);
	m_粒子大小.m_私有 = true;

	m_随机大小 = f_alloc_BoolProp(nullptr, u"随机大小");
	m_随机大小.m_私有 = true;

	m_随机大小区间 = f_alloc_Vec2Prop(nullptr, u"大小区间");
	m_随机大小区间.m_私有 = true;


	f_prop_LineStr(m_系统名称) = u"粒子系统";
	f_prop_Bool(m_随机大小) = false;



	m_坐标属性名称 = f_alloc_LineStrProp(nullptr, u"坐标属性", u"粒子坐标");
	m_旋转属性名称 = f_alloc_LineStrProp(nullptr, u"旋转属性", u"粒子旋转");
	m_速度属性名称 = f_alloc_LineStrProp(nullptr, u"速度属性", u"粒子速度");
	m_大小属性名称 = f_alloc_LineStrProp(nullptr, u"大小属性", u"粒子大小");
	m_寿命属性名称 = f_alloc_LineStrProp(nullptr, u"寿命属性", u"粒子寿命");
	m_年龄属性名称 = f_alloc_LineStrProp(nullptr, u"年龄属性", u"粒子年龄");
	
	m_坐标属性名称.m_私有 = true;
	m_旋转属性名称.m_私有 = true;
	m_速度属性名称.m_私有 = true;
	m_大小属性名称.m_私有 = true;
	m_寿命属性名称.m_私有 = true;
	m_年龄属性名称.m_私有 = true;

}

C_粒子系统节点::~C_粒子系统节点() {
	f_prop_Release(m_包含属性);

	f_prop_Release(m_粒子数量);
	f_prop_Release(m_系统名称);
	f_prop_Release(m_粒子寿命);
	f_prop_Release(m_寿命随机比);
	f_prop_Release(m_粒子大小);
	f_prop_Release(m_随机大小);
	f_prop_Release(m_随机大小区间);

	f_prop_Release(m_坐标属性名称);
	f_prop_Release(m_旋转属性名称);
	f_prop_Release(m_速度属性名称);
	f_prop_Release(m_大小属性名称);
	f_prop_Release(m_寿命属性名称);
	f_prop_Release(m_年龄属性名称);

	f_phy_销毁物理体(m_物理体);
}

bool C_粒子系统节点::f_update() {
	auto* 渲染物体 = DEF_物体插座_1D数据(f_get输入插座(2));

	auto* out物理体 = DEF_物理体插座_1D数据(f_get输出插座(1));
	uint32 old_num = out物理体->count;

	f_node_物体添加到全局容器(m_物理体);
	
	
	f_core_array_resize((S_Array*)out物理体, 1);
	out物理体->ptr_userData[0] = m_物理体;

	auto 粒子数量 = f_prop_UI32(m_粒子数量);

	
	m_物理体->m_物理体类型 = E_物理体类型::E_物理体_流入;

	if (m_物理体->m_Data == nullptr) {
		m_默认粒子系统 = f_ob_创建(m_Ctx, E_物体类型::t_粒子系统);
		f_node_构建物体模型(m_默认粒子系统, m_Ctx);
		m_物理体->m_Data = m_默认粒子系统;

		f_node_物体添加到主场景(m_默认粒子系统);
	}


	S_粒子系统配置* psys = f_ob_fromParticle(m_默认粒子系统);
	psys->m_包含属性 = f_prop_UI32位域枚举(m_包含属性);

	

	switch (f_prop_enum(m_渲染类型)) {
		case E_粒子渲染类型::e_空: {
			f_particle_设置渲染物体数量(psys, 0);
			break;
		}
		case E_粒子渲染类型::e_球体: {
			f_particle_设置渲染物体数量(psys, 1);
			f_surface_材质面区间(f_buf_getGlobal().g_粒子球体网格, f_NodeCtx_get基本光照面材质());
			
			psys->m_渲染物体网格[0] = f_buf_getGlobal().g_粒子球体网格;
			break;
		}
		case E_粒子渲染类型::e_方体: {
			f_particle_设置渲染物体数量(psys, 1);
			f_surface_材质面区间(f_buf_getGlobal().g_粒子方体网格, f_NodeCtx_get基本光照面材质());

			psys->m_渲染物体网格[0] = f_buf_getGlobal().g_粒子方体网格;
			break;
		}
		case E_粒子渲染类型::e_模型: {
			f_particle_设置渲染物体数量(psys, 渲染物体->count);
			uint32 渲染物体数量 = 0;
			for (uint32 i = 0; i < 渲染物体->count; ++i) {
				auto* me = f_ob_get光追网格(渲染物体->ptr_userData[i]);
				if (me) {
					psys->m_渲染物体网格[渲染物体数量] = me;
					++渲染物体数量;
				}
			}
			psys->m_渲染物体数量 = 渲染物体数量;
			break;
		}
		default:
			break;
	}

	f_set粒子数量(psys, 粒子数量);



	m_默认粒子系统->m_实例自定义属性区间偏移.clear();
	if (psys->m_包含属性 & E_粒子更新属性::e_pu_位置) {
		auto name = f_prop_WStr(m_坐标属性名称);
		m_默认粒子系统->m_实例自定义属性区间偏移[name] = &psys->m_Loc;
	}
	if (psys->m_包含属性 & E_粒子更新属性::e_pu_旋转) {
		auto name = f_prop_WStr(m_旋转属性名称);
		m_默认粒子系统->m_实例自定义属性区间偏移[name] = &psys->m_Rot;
	}
	if (psys->m_包含属性 & E_粒子更新属性::e_pu_速度) {
		auto name = f_prop_WStr(m_速度属性名称);
		m_默认粒子系统->m_实例自定义属性区间偏移[name] = &psys->m_Vel;
	}
	if (psys->m_包含属性 & E_粒子更新属性::e_pu_大小) {
		auto name = f_prop_WStr(m_大小属性名称);
		m_默认粒子系统->m_实例自定义属性区间偏移[name] = &psys->m_Size;
	}
	if (psys->m_包含属性 & E_粒子更新属性::e_pu_寿命) {
		auto name = f_prop_WStr(m_寿命属性名称);
		m_默认粒子系统->m_实例自定义属性区间偏移[name] = &psys->m_寿命;
	}
	if (psys->m_包含属性 & E_粒子更新属性::e_pu_年龄) {
		auto name = f_prop_WStr(m_年龄属性名称);
		m_默认粒子系统->m_实例自定义属性区间偏移[name] = &psys->m_年龄;
	}
	

	psys->m_初始寿命 = f_prop_F32(m_粒子寿命);
	psys->m_寿命随机比 = f_prop_F32(m_寿命随机比);

	psys->m_随机大小 = f_prop_Bool(m_随机大小);
	psys->m_初始粒子大小 = f_prop_F32(m_粒子大小);
	psys->m_大小区间 = f_prop_Vec2(m_随机大小区间);

	return false;
}

void C_粒子系统节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	auto 文件块 = f_file_读取文件块(f);

	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;
		下一次读取数据指针 = f_prop_Load(m_包含属性, 下一次读取数据指针);

		下一次读取数据指针 = f_prop_Load(m_渲染类型, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_粒子数量, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_系统名称, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_粒子寿命, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_寿命随机比, 下一次读取数据指针);

		下一次读取数据指针 = f_prop_Load(m_粒子大小, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_随机大小, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_随机大小区间, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_粒子系统节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);

	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));
	f_prop_Save(m_包含属性, 块);

	f_prop_Save(m_渲染类型, 块);
	f_prop_Save(m_粒子数量, 块);
	f_prop_Save(m_系统名称, 块);
	f_prop_Save(m_粒子寿命, 块);
	f_prop_Save(m_寿命随机比, 块);

	f_prop_Save(m_粒子大小, 块);
	f_prop_Save(m_随机大小, 块);
	f_prop_Save(m_随机大小区间, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建粒子系统节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_粒子系统节点(ctx);
}

C_节点基类* f_node_加载粒子系统节点(S_设备环境& ctx, FILE* f) {
	C_粒子系统节点* node = new C_粒子系统节点(ctx);
	return node;
}

void f_node_保存粒子系统节点(C_节点基类* n, FILE* f) {
	C_粒子系统节点* node = dynamic_cast<C_粒子系统节点*>(n);
}






C_发射节点::C_发射节点(S_设备环境& ctx) : C_节点基类(DEF_发射节点, E_节点类型::e_节点Type_解算) {
	f_setWName(u"发射节点");

	C_插座基类* socket;
	DEF_创建物理引擎插座_I(u"物理引擎");
	DEF_创建Vec3_1D插座_I(u"点");
	DEF_创建Vec3_1D插座_I(u"速度");
	//DEF_创建F32_1D插座_I(u"大小");
	
	DEF_创建物理引擎插座_O(u"物理引擎");

	m_发射方式 = f_alloc_EnumProp(nullptr, {}, u"");
	m_发射方式.m_私有 = true;

	m_粒子系统 = f_alloc_Object(nullptr, u"粒子系统");
	m_粒子系统.m_私有 = true;

	
	m_自定义更新方式 = true;
	m_更新方式 = E_节点更新方式::e_节点更新_逐帧;
}

C_发射节点::~C_发射节点() {
	f_prop_Release(m_发射方式);
	f_prop_Release(m_粒子系统);
	
}

bool C_发射节点::f_update() {
	auto* m_Physics = DEF_物理引擎插座数据(f_get输入插座(1), 0);

	if (!m_Physics) return false;
	f_get输出插座(1)->f_setData(m_Physics);

	if (f_更新是否跳过()) {
		return false;
	}

	f_NodeCtx_节点模拟入栈(this, false);
	return false;
}

void C_发射节点::f_异步解算() {
	auto* socket1 = f_get输入插座(1);
	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输出插座(1));

	auto* 发射点坐标 = DEF_Vec3插座_1D数据(f_get输入插座(2));
	auto* 发射点速度 = DEF_Vec3插座_1D数据(f_get输入插座(3));
	//auto* 粒子大小 = DEF_F32插座_1D数据(f_get输入插座(4));
	//S_物理体* body = f_phy_get物理体(解算器, f_prop_Object(m_粒子系统));

	f_prop_ObjectMat(m_粒子系统, &m_Physics->m_流入);

	S_物理体* body = dynamic_cast<S_物理体*>(f_prop_Object(m_粒子系统));
	if (body) {
		f_phy_发射粒子(m_Physics, body, 发射点坐标, 发射点速度);
	}
}

void C_发射节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	auto 文件块 = f_file_读取文件块(f);

	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;
		下一次读取数据指针 = f_prop_Load(m_发射方式, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_粒子系统, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_发射节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);

	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));
	f_prop_Save(m_发射方式, 块);
	f_prop_Save(m_粒子系统, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建发射节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_发射节点(ctx);
}

C_节点基类* f_node_加载发射节点(S_设备环境& ctx, FILE* f) {
	C_发射节点* node = new C_发射节点(ctx);
	return node;
}

void f_node_保存发射节点(C_节点基类* n, FILE* f) {
	C_发射节点* node = dynamic_cast<C_发射节点*>(n);

}





C_力对象节点::C_力对象节点(S_设备环境& ctx) : C_节点基类(DEF_作用力节点, E_节点类型::e_节点Type_物理力) {
	f_setWName(u"力");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建物体_1D插座_I(u"物体");
	DEF_创建F32_1D插座_I(u"力大小");
	//DEF_创建F32_1D插座_I(u"衰减");
	
	DEF_创建物体_1D插座_O(u"力物体");

	auto* 力大小 = DEF_F32插座_1D数据(f_get输入插座(2), 0);
	力大小->ptr_userData[0] = 0.1;


	m_力类型 = f_alloc_EnumProp(nullptr, {
		{u"单向"},
		{u"中心"},
		{u"旋转"},
		{u"湍流"},
	}, u"类型");
	m_力类型.m_私有 = true;

	m_使用范围 = f_alloc_BoolProp(nullptr, u"使用范围", false);
	m_使用范围.m_私有 = true;

	m_范围形状 = f_alloc_EnumProp(nullptr, {
		{u"球体"},
		{u"圆柱"},
		}, u"");
	m_范围形状.m_私有 = true;

	m_最小范围 = f_alloc_F32Prop(nullptr, u"最小范围", 1);
	m_最小范围.m_私有 = true;
	m_最大范围 = f_alloc_F32Prop(nullptr, u"最大范围", 1);
	m_最大范围.m_私有 = true;

	m_范围最小高度 = f_alloc_F32Prop(nullptr, u"最小高度", 1);
	m_范围最小高度.m_私有 = true;
	m_范围最大高度 = f_alloc_F32Prop(nullptr, u"最大高度", 1);
	m_范围最大高度.m_私有 = true;

	m_自定义更新方式 = true;
	m_更新方式 = E_节点更新方式::e_节点更新_逐帧;
}

C_力对象节点::~C_力对象节点() {
	f_prop_Release(m_力类型);
	f_prop_Release(m_使用范围);

	f_prop_Release(m_范围形状);
	f_prop_Release(m_最小范围);
	f_prop_Release(m_最大范围);
	f_prop_Release(m_范围最小高度);
	f_prop_Release(m_范围最大高度);
}

bool C_力对象节点::f_update() {
	auto inSocket1 = f_get输入插座(1);
	auto* 力大小 = DEF_F32插座_1D数据(f_get输入插座(2), 0);
	auto* 力物体 = DEF_物体插座_1D数据(f_get输出插座(1), 0);
	

	if (inSocket1->f_isLink()) {
		auto* 物体 = DEF_物体插座_1D数据(inSocket1, 0);

		f_node_创建模型物体组(力物体, 物体->count, E_物体类型::t_虚拟体, m_Ctx, E_物体类型::t_物理力);
	}
	else {
		f_node_创建模型物体组(力物体, 1, E_物体类型::t_虚拟体, m_Ctx, E_物体类型::t_物理力);
	}
	
	bool 使用范围 = f_prop_Bool(m_使用范围);
	E_形状 形状 = E_形状(f_prop_enum(m_范围形状));


	bool 力大小多例 = 力大小->count >= 力物体->count;
	for (uint32 i = 0; i < 力物体->count; ++i) {
		S_PBF_force& 力 = *(S_PBF_force*)力物体->ptr_userData[i]->m_UserData;

		力.m_intensity = 力大小多例 ? 力大小->ptr_userData[i] : 力大小->ptr_userData[0];
		力.m_type_limits = f_prop_enum(m_力类型);
		力.m_point = f_ob_get全局坐标(力物体->ptr_userData[i], 0);

		switch (力.m_type_limits) {
			case DEF_ForceType_unidirectional: {
				f_node_虚拟体_设置单向力虚拟网格(力物体->ptr_userData[i], 形状, 使用范围);

				力.m_dir = _Vec4(f_ob_get变换矩阵(力物体->ptr_userData[i], 0) * vec3{0, 1, 0}, 力.m_intensity);
				
				break;
			}
			case DEF_ForceType_radial: {
				f_node_虚拟体_设置径向力虚拟网格(力物体->ptr_userData[i], 形状, 使用范围);

				力.m_dir = _Vec4(f_ob_get变换矩阵(力物体->ptr_userData[i], 0) * vec3 { 0, 1, 0}, 力.m_intensity);
				break;
			}
			case DEF_ForceType_rotate: {
				f_node_虚拟体_设置旋转力虚拟网格(力物体->ptr_userData[i], 形状, 使用范围);

				auto rot = f_mat44_3x3(f_ob_get变换矩阵(力物体->ptr_userData[i], 0));
				力.m_dir = f_graph_从轴向角度计算四元数(rot * vec3 { 0, 1, 0}, 1);
				break;
			}
			case DEF_ForceType_turbulence: {
				f_node_虚拟体_设置涡流力虚拟网格(力物体->ptr_userData[i], 形状, 使用范围);

				break;
			}
		}
		
		力.m_type_limits = 力.m_type_limits << 16;
		

		if (使用范围) {
			
			vec2 范围 = _Vec2(f_prop_F32(m_最小范围), f_prop_F32(m_最大范围));
			if (范围.x > 范围.y) {
				范围.x = 范围.y;
				f_prop_F32(m_最小范围) = f_prop_F32(m_最大范围);
			}

			vec2 高度 = _Vec2(f_prop_F32(m_范围最小高度), f_prop_F32(m_范围最大高度));
			if (高度.x > 高度.y) {
				高度.x = 高度.y;
				f_prop_F32(m_范围最小高度) = f_prop_F32(m_范围最大高度);
			}

			f_node_虚拟体_设置力范围网格大小(力物体->ptr_userData[i], 形状, 范围, 高度);

			力.m_limitsR = 范围 * 0.5;
			力.m_limitsH = 高度 * 0.5;

			力.m_type_limits |= 1;
			switch (形状) {
				case E_形状::e_shape球体: 力.m_type_limits |= DEF_ShapeType_sphere << 8; break;
				case E_形状::e_shape圆柱: 力.m_type_limits |= DEF_ShapeType_cylinder << 8; break;
				case E_形状::e_shape方体: 力.m_type_limits |= DEF_ShapeType_box << 8; break;
				default:
					break;
			}
		}
	}


	return false;
}

void C_力对象节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	auto 文件块 = f_file_读取文件块(f);

	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;
		下一次读取数据指针 = f_prop_Load(m_力类型, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_使用范围, 下一次读取数据指针);

		下一次读取数据指针 = f_prop_Load(m_范围形状, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_最小范围, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_最大范围, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_范围最小高度, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_范围最大高度, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_力对象节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);

	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));
	f_prop_Save(m_力类型, 块);
	f_prop_Save(m_使用范围, 块);

	f_prop_Save(m_范围形状, 块);
	f_prop_Save(m_最小范围, 块);
	f_prop_Save(m_最大范围, 块);
	f_prop_Save(m_范围最小高度, 块);
	f_prop_Save(m_范围最大高度, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建力对象节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_力对象节点(ctx);
}

C_节点基类* f_node_加载力对象节点(S_设备环境& ctx, FILE* f) {
	C_力对象节点* node = new C_力对象节点(ctx);
	return node;
}

void f_node_保存力对象节点(C_节点基类* n, FILE* f) {
	C_力对象节点* node = dynamic_cast<C_力对象节点*>(n);

}









//rot.x = -body->m_变换.rotation.x;
			//rot.y = -body->m_变换.rotation.y;
			//rot.z = -body->m_变换.rotation.z;



			//std::string 位置 = "pos = \" ";
			//std::string 大小 = "size = \" ";
			//std::string gepm_type;
			//switch (body->m_Type) {
			//case E_物理几何体类型::E_碰撞几何_方体:
			//	gepm_type = "box";
			//	break;
			//case E_物理几何体类型::E_碰撞几何_圆柱:
			//	break;
			//case E_物理几何体类型::E_碰撞几何_球体:
			//	break;
			//case E_物理几何体类型::E_碰撞几何_胶囊:
			//	break;
			//case E_物理几何体类型::E_碰撞几何_凸壳:
			//	break;
			//case E_物理几何体类型::E_碰撞几何_平面:
			//	gepm_type = "plane";
			//	break;
			//case E_物理几何体类型::E_碰撞几何_网格:
			//	break;
			//}
			//
			//auto mat = f_ob_get实例变换矩阵((S_物体*)ob->m_绑定物体, 0);
			//
			//vec3 pos = mat * vec3{ 0,0,0 };
			//vec3 rot = body->m_变换.rotation;
			//
			//位置 += f_浮点数值转字符串(body->m_变换.location.x) + " ";
			//位置 += f_浮点数值转字符串(body->m_变换.location.z) + " ";
			//位置 += f_浮点数值转字符串(body->m_变换.location.y) + " ";
			//位置 += "\" ";
			//
			//大小 += f_浮点数值转字符串(body->m_变换.scale.x) + " ";
			//大小 += f_浮点数值转字符串(body->m_变换.scale.z) + " ";
			//大小 += f_浮点数值转字符串(body->m_变换.scale.y) + " ";
			//大小 += "\" ";
			//
			//std::string 旋转 = " euler = \" ";
			//
			//rot.x = -body->m_变换.rotation.x;
			//rot.y = -body->m_变换.rotation.y;
			//rot.z = -body->m_变换.rotation.z;
			//vec4 q = f_graph_欧拉角转四元数(rot);
			//
			//auto rotMat = f_mat44_构建XYZ旋转矩阵(body->m_变换);
			//
			//q = f_graph_旋转角转四元数(rot);
			//
			//旋转 += f_浮点数值转字符串((rot.z)) + " ";
			//旋转 += f_浮点数值转字符串((rot.x)) + " ";
			//旋转 += f_浮点数值转字符串((rot.y)) + " ";
			//
			//旋转 += "\" ";
			//
			//body->m_XML = "	<body " + 位置 + 旋转 +"> \n";
			//
			//switch (物理体类型)
			//{
			//case E_物理体类型::E_物理体_刚体:
			//	body->m_XML += "	<freejoint /> \n";
			//	break;
			//case E_物理体类型::E_物理体_静态:
			//	break;
			//default:
			//	break;
			//}
			//
			//body->m_XML += "	<geom type = \"" + gepm_type + "\" " + 大小 +"/> \n";
			//body->m_XML += "	</body> \n";